
/*
 * File:   tools.c
 * Author: Ewelle
 *
 * Created on November 17, 2009, 10:09 AM
 */
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <string.h>
#include <dirent.h>
#include "tools.h"
#include "myFtp.h"

/*
 *   Obtenir la liste du contenu d'un repertoire
 */

char **getdir (char *rep)
{
    DIR *dir = opendir(rep);
    static char* result;
    char liste[MAX_BUFF_SIZE]="\0";
    if(dir)
    {
        struct dirent *ent;
        while((ent = readdir(dir)) != NULL)
        {
            if ((unsigned) ent->d_type==4)
                sprintf(liste, "%s %20s    [DIR]\n", liste,ent->d_name);
            else
                sprintf(liste, "%s %20s\n", liste,ent->d_name);
        }
    }
    else
    {
        result="null";
        return &result;
    }
    result=liste;
    return &result;
}

/*
 *   Spliter la commande entrée par l'utilisateur en commande plus arguments
 */

void split(char *original, char * split1, char * split2, char del)
{
  int i = 0;
  int j = 0;
  int flag = 0;

  while (original[i] != '\0')
  {
     if (flag == 0)
     {
        if (original[i] == del)
        {
           flag = 1;
           split1[i] = '\0';
        }
        else
        {
           split1[i] = original[i];
        }
     }
     else
     {
        split2[j++] = original[i];
     }
     i++;
  }
  split2[j-1] = '\0';
  if(flag==0)
  {
   split1[i-1] = '\0';
   split2[0] = 'n';
   split2[1] = 'u';
   split2[2] = 'l';
   split2[3] = 'l';
   split2[4] = '\0';
  }
}

/*
 *   Lire un bloc de donné d'un fichier
 */

data_i * read_local(read_option *option){

    static data_i result;
    int k = 0,r=0;
    result.buf = (char*) malloc (sizeof(char)*BUFF_SIZE);

    if(option->pos == 0){
    	while ((read(option->fd,&(Buffer_Reader[k]),1) != -1) && k < MAX_BUFF_SIZE){
		if( k< BUFF_SIZE){
		      result.buf[k] = Buffer_Reader[k];
                      r++;
		}
		k++;
    	}
    result.buf[r-1] = '\0';
    result.len = strlen(result.buf);


    }
    else{
	int s =0;
	int t = 0;
	fputs("Nouvelle requete",stderr);
	t = option->pos;
	for( t= option->pos, s=0;Buffer_Reader[t]!='\0' && s < BUFF_SIZE ;s++,t++){
		result.buf[s] = Buffer_Reader[t];
	}

    	result.buf[t-1] = '\0';
	fputs(result.buf,stderr);

    }

    return(&result);
};

/*
 *   Exécution de la commande put d'un fichier à l'autre
 */

int putFile(char inFile[255],char outFile[255], CLIENT *cl) {

  struct open_out fd;
  int *fd1;
  open_file openArg;
  data_o dataoArg;
  int size;
  FILE *fic;

  openArg.filename=(char*) malloc (sizeof(char)*FN_SIZE);
  strcpy(openArg.filename,outFile);
  openArg.rw=1;

  // ouverture du fichier distant en lecture
  fd1 = open_1(&openArg, cl);
  if(fd1 == NULL){
    printf("Probleme d'ouverture du fichier %s\n", outFile);
    return 0;
  }
  // ouverture du fichier local en ecriture

  fic = fopen(inFile,"r");
  if(fic == NULL){
    printf("Probleme d'ouverture du fichier %s\n", inFile);
    return 0;
  }
    fseek (fic , 0 , SEEK_END);
    size = ftell (fic);
    fclose(fic);

    //fixe le descripteur de fichier
    fd.fd = open(inFile,O_RDWR);
    //donne la taille du fichier
    fd.size = size;

//taille du openArg a telecharger
    size = fd.size;
if(fd.fd != 0){
    struct read_option read;
    read.fd = fd.fd;
    read.pos = 0;

    //lecture du premier bloc de donnees

    struct data_i *lecture = read_local(&read);
    long lsize = lecture->len;

    dataoArg.fd=*fd1;
    dataoArg.buf=lecture->buf;
    dataoArg.len=lecture->len;

    write_1(&dataoArg, cl);
    if(lsize < size){
       while(lsize < size){
            read.fd = fd.fd;
            read.pos = (int)lsize;
            lecture = read_local(&read);
            dataoArg.fd=*fd1;
            dataoArg.buf=lecture->buf;
            dataoArg.len=lecture->len;
            write_1(&dataoArg, cl);
            lsize = lecture->len + lsize;
       }
    }

  }

  // fermeture du fichier de distant
  if(close_1(fd1, cl) == 0) {
      printf("Probleme de fermeture du fichier %s\n", outFile);
      return 0;
  }

    close(fd.fd);
  // fermeture du fichier locale
  //if(close(fd.fd) == 0) {
  //    printf("Probleme de fermeture du fichier %s\n", inFile);
  //    return 0;
  //}
  return 1;
}

/*
 *   Exécution de la commande get d'un fichier à l'autre
 */

int getFile(char inFile[255],char outFile[255], CLIENT *cl) {

  int *fd;
  open_file openArg;
  FILE *fic;

  openArg.filename=(char*) malloc (sizeof(char)*FN_SIZE);
  strcpy(openArg.filename,inFile);
  openArg.rw=0;

  // ouverture du fichier distant en lecture
  fd = open_1(&openArg, cl);
  if(fd == NULL){
    printf("Probleme d'ouverture du fichier %s\n", inFile);
    return 0;
  }

  // ouverture du fichier local en ecriture
  fic = fopen(outFile, "w");
  if(fic == NULL){
    printf("Probleme d'ouverture du fichier %s\n", outFile);
    return 0;
  }

if(*fd != 0){
    struct data_i *lecture = read_1(fd,cl);
    long lsize = lecture->len;
    while(lsize>4){
        fputs(lecture->buf,fic);
        lecture = read_1(fd,cl);
        lsize = lecture->len;
       }
    }

  // fermeture du fichier de distant
  if(close_1(fd, cl) == 0) {
      printf("Probleme de fermeture du fichier %s\n", inFile);
      return 0;
  }

  // fermeture du fichier locale
  if(fclose(fic) == EOF) {
      printf("Probleme de fermeture du fichier %s\n", outFile);
      return 0;
  }
  return 1;
}


//Pile des clients

// Insérer un nouveau client dans la liste

clients *inserer(clients *list, struct client cli)
{ clients *vlist_item;
  int n;
  clients *vlist_move;
  /* on alloue la memoire pour le nouvel element */
  if((vlist_item = (clients *)malloc(sizeof(clients))) == NULL)

  { perror("malloc failed "); exit(1); }

  /* on recopie la valeur */
  strcpy(vlist_item->ip, cli.ip);
  vlist_item->port  = cli.port;
  strcpy(vlist_item->m_env,cli.m_env);
  vlist_item->m_status  = cli.m_status;
  strcpy(vlist_item->m_value, cli.m_value);

  /* on chaine avec le prochain element de la liste
     (aucun car on est le dernier) */
  vlist_item->next = NULL;

  if(list == NULL)
  { /* la liste etait vide, on devient le premier element */

    return(vlist_item);
  } else {
    /* on parcour la liste jusqu'au dernier element
       (celui qui pointe sur NULL) */

    for(vlist_move=list;vlist_move->next!=NULL;vlist_move=vlist_move->next);

    /* le dernier element pointe maitenant sur le nouvel element */
    vlist_move->next = vlist_item;


    /* le premier element de la liste n'a pas change */
    return(list);

  }
}

/*
 *   Modifier les informations du client
 */

clients *update(clients *list, struct client cli)
{ clients *vlist_move;
  clients *vlist_move_prev;

  vlist_move_prev = NULL;

  for(vlist_move=list;(vlist_move!=NULL) && ((vlist_move->port!=cli.port));
      vlist_move_prev=vlist_move,vlist_move=vlist_move->next);

  if(vlist_move != NULL)
  {
     strcpy(vlist_move->ip,cli.ip);
     vlist_move->port=cli.port;
     strcpy(vlist_move->m_env,cli.m_env);
     vlist_move->m_status=cli.m_status;
     strcpy(vlist_move->m_value,cli.m_value);

  }
  	return(list);
}


/* permet de supprimer un element dans la liste en */
/* connaissant sa valeur                           */
/* renvoie la nouvelle liste cree                  */
clients *supprimer(clients *list, char *ip,int port)

{ clients *vlist_move;
  clients *vlist_move_prev;
  clients *vlist_tmp;

  /* on recherche l'element avec la valeur val dans la liste */
  /* on conserve aussi dans vlist_move_prev l'element qui le */
  /* precende dans la liste.                                 */
  vlist_move_prev = NULL;

  for(vlist_move=list;(vlist_move!=NULL) && (vlist_move->port!=port||(strcmp(vlist_move->ip,ip)!=0));

      vlist_move_prev=vlist_move,vlist_move=vlist_move->next);

  if(vlist_move == NULL)

  { /* l'element n'existe pas dans la liste   */
    /* on ne peut donc pas le supprimer.      */
    /* on sait cela car NULL indique que l'on */
    /* est alle au dela de la fin de la liste */
    return(list);

  } else {
    if(vlist_move_prev == NULL)

    { /* pas d'element avant, on etait le permier */
      /* on conserve l'element suivant            */
      vlist_tmp = vlist_move->next;

      /* on libere la memoire de l'element que l'on devait trouver */
      free(vlist_move);
      /* l'element suivant devient le premier de la liste */
      return(vlist_tmp);

    } else {
      /* l'element d'avant indique maintenant le suivant          */
      /* de l'element trouve (on cours circuite l'element trouve) */
      vlist_move_prev->next = vlist_move->next;

      /* on libere l'element trouve */
      free(vlist_move);
      /* le premier de la liste n'a pas change */
      return(list);

    }
  }
}


// Teste l'existence d'un client dans la liste
struct client eXist(clients *list, char ip[255], int port)
{ clients *vlist_move;
  clients *vlist_move_prev;
  struct client cli;

  vlist_move_prev = NULL;

  for(vlist_move=list;(vlist_move!=NULL) && ((strcmp(vlist_move->ip,ip)!=0)||(vlist_move->port!=port));
      vlist_move_prev=vlist_move,vlist_move=vlist_move->next);

  if(vlist_move == NULL)
      cli.port=-1;
  else{
     strcpy(cli.ip, vlist_move->ip);
     cli.port= vlist_move->port;
     strcpy(cli.m_env, vlist_move->m_env);
     cli.m_status= vlist_move->m_status;
     strcpy(cli.m_value, vlist_move->m_value);

  }
  	return cli;
}

// Liste les clients présentements dans le système
int listClient(clients *list)
{ clients *vlist_move;
  int count =0;

  for(vlist_move=list;(vlist_move!=NULL);vlist_move=vlist_move->next)
  {
    fprintf (stderr, "Port:%d IP:%s PWD:%s\n", vlist_move->port,vlist_move->ip,vlist_move->m_value);
    count ++;
  }
  return count;
}

/*
 *   Renseigner les variable d'environement pour un client
 */
void setPwd(struct svc_req *rqstp){

    char *ip;
    int port,out,n;
    struct client cli;
    ip = inet_ntoa(rqstp->rq_xprt->xp_raddr.sin_addr);
    port = (int)rqstp->rq_xprt->xp_raddr.sin_port;
    cli=eXist(liste_Clients,ip,port);
    out=chdir(cli.m_value);
};

/*
 *   Mettre à jour les variable d'environement pour un client après un Cd
 */
void updatePwd(struct svc_req *rqstp){

    static bool_t result;
    char path[MAXPATHLEN];
    char *ip;
    int port,n;
    struct client cli;
    result=1;
    getcwd(path, MAXPATHLEN);
    ip = inet_ntoa(rqstp->rq_xprt->xp_raddr.sin_addr);
    port = (int)rqstp->rq_xprt->xp_raddr.sin_port;
    cli=eXist(liste_Clients,ip,port);
    strcpy(cli.m_env,path);
    strcpy(cli.m_value,path);
    liste_Clients = update(liste_Clients, cli);
    fprintf (stderr, "Update Port:%d IP:%s PWD:%s\n\n", cli.port,cli.ip,cli.m_value);
};

